/*
 * @desc 验证
 * */
define(['valider', 'jquery', 'query', 'ajaxer', 'objecter', 'dialoger'], function(Valider, $, query, ajaxer, objecter, dialoger){
    var validater = {
        validate : function(opts){
            options = objecter.extend({}, defaults, opts);
            if(init) init();
            init = null;
        },

        //添加验证方法
        addMethod : function(){
            valider.addMethod.apply(valider, arguments);
        },

        //提示设置
        messages : function(){
            valider.messages.apply(valider, arguments);
        },

        //检测验证
        isValid : function(el){
            return valider.isValid(el);
        },

        //设置配置
        setOptions : function(opts){
            options = objecter.extend({}, options, opts);
        }
    },

    //默认配置
    defaults = {
        //显示名键
        validName : 'data-valid-name',
        //以ajax发送表单
        ajax : null,
        //失去焦点时检测
        blurValidate : true,
        //错误信息父级容器
        errorParent : '.form-grep',
        //统一的错误信息父级容器
        errorContainer : null,
        //单个错误信息父级容器
        selfErrorContainer : null,
        //控制错误显示与隐藏
        errorShowAble : false,
        //错误类名
	    invalidClass : 'has-error',
        //验证通过类名
        validClass : 'has-success',
        //生成的错误元素类型
        errorClass : 'help-block',
        //聚焦在错误元素上
        errorFocus : false,
        //以弹出形式显示错误
        alertShow : false,

        //在线验证发送到服务端的额外参数
        params : {}
    }, options = defaults;

    //初始化
    function init(){
        var els = query.find(options.el), arr = [], timer;
        //找出所有表单元素
        for(var i = 0, temp; i < els.length; i++){
            temp = els[i];
            if(/form/i.test(temp.tagName)){
                if(temp.isBindvalid) break;
                temp.isBindvalid = 1;
	            temp.novalidate='novalidate';
	            temp.setAttribute('novalidate', 'novalidate');
                //表单发送时检测
                bindForm(temp);
                arr = arr.concat(query.find('input,select,textarea', temp));
            }else if(/input|select|textarea/i.test(temp.tagName)){
                arr = arr.concat(temp);
            }
        }

        for(var i = 0, el; i < arr.length; i++){
            if(arr[i].isBindvalid) break;
            arr[i].isBindvalid = 1;
            bindInput(arr[i]);
        }

        //表单元素事件绑定
        function bindInput(el){
            var type = 'blur';
            if(/select/i.test(el.tagName)){
                type = 'change';
            }
            else if(/radio|checkbox/i.test(el.type)){
                type = 'mouseup';
            }

            addEventListener(el, type, function(){
                if(options.blurValidate){
                    timer = setTimeout(function(){
                        valider.isValid(el);
                    }, 200);
                }
            });
        }

        //表单form发送绑定
        function bindForm(el){
            el.setAttribute('novalidate', 'novalidate');
            addEventListener(el, 'submit', function(e){
                clearTimeout(timer);
                var b = valider.isValid(el);
                if(!b){
                    preventDefault(e);
                    return false;
                }

                if(typeof options.onSubmit == 'function'){
                    var result = options.onSubmit();
                }else if(options.submit === false || options.onSubmit === false){
                    result = false;
                }
                if(result === false){
                    preventDefault(e);
                    return false;
                }

                if(options.ajax == false){
                    return true;
                }
                preventDefault(e);
                setTimeout(function() {
                    require(['cruder'], function (cruder) {
                        cruder.ajaxForm({
                            form: $(el)
                        });
                    });
                }, 20);
                return false;
            });

            function preventDefault(e){
                e = e || window.event; // Event对象
                if (e.preventDefault) { // 标准浏览器
                    e.preventDefault();
                } else { // IE浏览器
                    window.event.returnValue = false;
                }
            }
        }
    }

    function addEventListener(element, eventType, handler, capture) {
        if (typeof capture != 'boolean') {
            capture = false;
        }

        if (element.addEventListener) {
            element.addEventListener(eventType, handler, capture);
        }
        else if (element.attachEvent) {
            if (capture) {
                element.setCapture();
            }
            element.attachEvent("on" + eventType, handler);
        }
        else {
            element["on" + eventType] = handler;
        }
    }

    //验证器
    var valider = new Valider();

    valider.setOptions({
        onSuccess : function(group){
            showError(false, group);
        },

        onError : function(group, msg){
            showError(true, group, msg);
        }
    });

    function showError(b, group, msg){
        var el = group.list[0], $element = $(el), $container, $error;

        //弹出显示
        if(options.alertShow && b) {
            var validName = el.getAttribute(options.validName);
            validName = validName ? validName + ':' : '';
            dialoger.error({msg : validName + msg});
        }

        //内联显示
        else if(options.errorParent){
            $container = $element.parents(options.errorParent);
            if(b) $container.removeClass(options.validClass).addClass(options.invalidClass);
            else $container.removeClass(options.invalidClass).addClass(options.validClass);
        }

        //单个错误指定容器
        if($container && options.selfErrorContainer){
            $error = $container.find(options.selfErrorContainer).empty();
        }
        //所有错误指定容器
        else if(options.errorContainer){
            $error = $(options.errorContainer).empty();
        }
        else if($container){
            $error = $container.find('.error-line');
            if($error.length < 1) $error = $('<span class="error-line"></span>').appendTo($container);
        }

        if($error){
            if(b){
                $error.html('<span class="' + options.errorClass + '">' + msg + '</span>');
                if(options.errorShowAble) $error.show();
            }else{
                $error.html('');
                if(options.errorShowAble) $error.hide();
            }
        }

        if(b && options.errorFocus) el.focus();
    }

    //消息设置
    valider.messages({
        required : '必填字段'
    });

    ////添加验证方法////
    valider.addMethod('nospace', function(value, element) {
        return !(/\s/.test(value));
    }, '含有空格');

    valider.addMethod('email', function(value, element) {
        return /^((([a-z]|\d|[!#\\$%&'\\*\\+\-\\/=\\?\\^_`{\\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i.test(value);
    }, '请输入正确格式的电子邮件');

    valider.addMethod('url', function(value, element) {
        return /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
    }, '请输入合法的网址');

    valider.addMethod('date', function (value, element) {
        value = value.replace(/\s+/g, "");
        return value.match(/^\d{4}.?\d{1,2}.?\d{1,2}.?\d{0,2}.?\d{0,2}.?\d{0,2}$/);
    }, '请输入合法的日期');

    valider.addMethod('dateearly', function(value, element, param) {
        var target = query.find(param), tarVal = '';
        if(target[0]) tarVal = target[0].value;
        return /^\d{4}.?\d{1,2}.?\d{1,2}.?\d{0,2}.?\d{0,2}.?\d{0,2}$/.test(tarVal) ? (value <= tarVal) : true;
    }, '请输入更早的日期');

    valider.addMethod('datelate', function(value, element, param) {
        var target = query.find(param), tarVal = '';
        if(target[0]) tarVal = target[0].value;
        return (/^\d{4}.?\d{1,2}.?\d{1,2}.?\d{0,2}.?\d{0,2}.?\d{0,2}$/.test(tarVal) ? (value >= tarVal) : true);
    }, '请输入更晚的日期');

    valider.addMethod('dateISO', function(value, element) {
        return /^\d{4}[\\/-]\d{1,2}[\\/-]\d{1,2}$/.test(value);
    }, '请输入合法的日期 (ISO)');

    valider.addMethod('number', function(value, element) {
        return /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value);
    }, '请输入合法的数字');

    valider.addMethod('digits', function(value, element) {
        return /^\d+$/.test(value);
    }, '只能输入整数');

    valider.addMethod('letnum', function (value, element, param) {
      return /\d/i.test(value) && /[a-zA-Z]/i.test(value);
    }, '请输入字母与数字组合');

    valider.addMethod('alphanumeric', function (value, element) {
        return /^\w+$/i.test(value);
    }, '字母、数字、下划线');

    valider.addMethod('lettersonly', function (value, element) {
        return /^[a-z]+$/i.test(value);
    }, '必须是字母');

    valider.addMethod('phone', function (value, element) {
        return /^[0-9\s\\(\\)]{7,30}$/.test(value);
    }, '请输入数字、空格或括号');

    valider.addMethod('cellphone', function (value, element) {
        return /^0{0,1}(13[0-9]|15[3-9]|15[0-2]|18[0-9])[0-9]{8}$/.test(value);
    }, '请输入手机号');

    valider.addMethod('postcode', function (value, element) {
        return /^[0-9 A-Za-z]{5,20}$/.test(value);
    }, '请输入验证码');

    valider.addMethod('zhcn', function(value, element) {
        return /^[\u4e00-\u9fa5]{0,}$/.test(value);
    }, '请输入汉字');

    valider.addMethod('phone-or-email', function(value, element, param) {
      return /^0{0,1}(13[0-9]|15[3-9]|15[0-2]|18[0-9])[0-9]{8}$/.test(value) || /^((([a-z]|\d|[!#\\$%&'\\*\\+\-\\/=\\?\\^_`{\\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i.test(value);
    }, '手机或邮箱');

    valider.addMethod('equalTo', function(value, element, param) {
      var target = query.find(param), tarVal = '';
      if(target[0]) tarVal = target[0].value;
      return tarVal == value;
    }, '请再次输入相同的值');

    valider.addMethod("accepts", function(value, element, param) {
      param = typeof param == 'string' ? param.replace(/,/g, '|') : 'png|jpe?g|gif';
      return value.match(new RegExp(".(" + param + ")$", "i"));
    }, '请输入拥有合法后缀名的字符串');

    valider.addMethod('maxlength', function (value, element, param) {
      return value.length <= parseInt(param);
    }, '长度最多是 {0} 的字符串');

    valider.addMethod('minlength', function (value, element, param) {
      return value.length >= parseInt(param);
    }, '长度最少是 {0} 的字符串');

    valider.addMethod('rangelength', function (value, element, param) {
      param = this.formateParams(param);
      return value.length >= parseInt(param[0]) && parseInt(param[1]) >= value.length;
    }, function (param) {
      param = this.formateParams(param);
      if (param[0] == param[1]) {
        return '长度应为 ' + param[0] + ' 个字符';
      }
      return '长度介于 ' + param[0] + ' 和 ' + param[1] + ' 之间的字符串';
    });

    valider.addMethod('max', function (value, element, param) {
      return value <= param;
    }, "请输入一个最大为 {0} 的值");

    valider.addMethod('min', function (value, element, param) {
      return value >= param;
    }, '请输入一个最小为 {0} 的值');

    valider.addMethod('range', function (value, element) {
      param = this.formateParams(param);
      return value >= parseInt(param[0]) && parseInt(param[1]) >= value;
    }, function (param) {
      param = this.formateParams(param);
      if (param[0] == param[1]) {
        return '值应为 ' + param[0];
      }
      return '请输入一个介于 ' + param[0] + ' 和 ' + param[1] + ' 之间的值';
    });

    valider.addMethod('pattern', function(value, element, param) {
      var reg = new RegExp(param, 'gi');
      return reg.test(value);
    }, '请输入规则字符');

    valider.addMethod("remote", function(value, element, param) {
        var data = {}, b = false, name = element[0].name || 'name';
        data = objecter.extend({}, options.params);
        data[name] = value;
        ajaxer.ajax({
            async : false,
            url : param,
            data : data,
            dataType : 'text',
            success : function(data, textStatus, XMLHttpRequest){
                data = data.replace(/^\s*|\s*$/g, '');
                if(/^\{.+\}$|^\[.+\]$/.test(data)){
                    data = (new Function('return ' + data))();
                }
                if(typeof data == 'object'){
                    b = (data.status >= 1) || (data.status == 'true') || (data.data >= 1) || (data.data == 'true');
                }else{
                    b = (data == 1) || (data == 'true');
                }
            },
            error : function(XMLHttpRequest, textStatus, errorThrown){
                b = false;
            }
        });

        return b;
    }, '已经存在,请修改后重试');

    return validater;
});